package com.rede.didiok.user.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.SQLConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.domainEvent.EventAction;
import com.rede.didiok.common.dto.admin.AdminDto;
import com.rede.didiok.common.dto.user.UserWatchDto;
import com.rede.didiok.common.enums.StatusEnum;
import com.rede.didiok.common.enums.WatchStatusEnum;
import com.rede.didiok.common.exception.exceptionType.FeignException;
import com.rede.didiok.common.exception.exceptionType.InsertException;
import com.rede.didiok.common.exception.exceptionType.QueryException;
import com.rede.didiok.common.feign.AdminFeignClient;
import com.rede.didiok.common.holder.RequestHolder;
import com.rede.didiok.common.utils.R;
import com.rede.didiok.common.utils.RedisUtil;
import com.rede.didiok.common.utils.ResultUtil;
import com.rede.didiok.common.utils.StringUtils;
import com.rede.didiok.common.utils.business.DomainEventUtil;
import com.rede.didiok.user.dao.UserWatchDao;
import com.rede.didiok.user.entity.UserEntity;
import com.rede.didiok.user.entity.UserWatchEntity;
import com.rede.didiok.user.service.UserService;
import com.rede.didiok.user.service.UserWatchService;


@Service("userWatchService")
public class UserWatchServiceImpl extends ServiceImpl<UserWatchDao, UserWatchEntity> implements UserWatchService {

    @Autowired
    private UserWatchService userWatchService;
    @Autowired
    private UserService userService;
    @Autowired
    private AdminFeignClient adminFeignClient;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private DomainEventUtil domainEventUtil;

    /***************************** admin:start **************************/
    // region  didiok-admin

    // endregion
    /***************************** admin:end **************************/



    /***************************** web:start **************************/
    // region didiok-web

    @Override
    public Boolean checkUserWatch(UserWatchDto userWatchDto) {
        QueryWrapper<UserWatchEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.CREATE_USER_UID, userWatchDto.getCreateUserUid());
        queryWrapper.eq(SQLConf.TO_USER_UID, userWatchDto.getToUserUid());
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        int count = userWatchService.count(queryWrapper);
        return count > 0;
    }

    @Override
    public Integer getUserWatchCount(UserWatchDto userWatchVO) {
        QueryWrapper<UserWatchEntity> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(userWatchVO.getCreateUserUid())) {
            queryWrapper.eq(SQLConf.CREATE_USER_UID, userWatchVO.getCreateUserUid());
        }
        if (StringUtils.isNotEmpty(userWatchVO.getToUserUid())) {
            queryWrapper.eq(SQLConf.TO_USER_UID, userWatchVO.getToUserUid());
        }
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        Integer userWatchCount = userWatchService.count(queryWrapper);
        return userWatchCount;
    }

    @Override
    public IPage<UserWatchEntity> getPageList(UserWatchDto userWatchDto) {
        QueryWrapper<UserWatchEntity> queryWrapper = new QueryWrapper<>();
        // 判断关注者和被关注者是否为空
        if (StringUtils.isEmpty(userWatchDto.getCreateUserUid()) && StringUtils.isEmpty(userWatchDto.getToUserUid())) {
            throw new QueryException(MessageConf.PARAM_INCORRECT);
        }
        // 状态标志位，判断是否获取关注者 还是 被关注者【主要是通过userUid和toUserUid来进行判断】
        Boolean isWatch = false;
        // 获取TA关注了谁
        if (StringUtils.isNotEmpty(userWatchDto.getCreateUserUid())) {
            isWatch = true;
            queryWrapper.eq(SQLConf.CREATE_USER_UID, userWatchDto.getCreateUserUid());
        }
        // 获取TA的粉丝
        if (StringUtils.isNotEmpty(userWatchDto.getToUserUid())) {
            isWatch = false;
            queryWrapper.eq(SQLConf.TO_USER_UID, userWatchDto.getToUserUid());
        }
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        Page<UserWatchEntity> page = new Page<>();
        page.setCurrent(userWatchDto.getCurrentPage());
        page.setSize(userWatchDto.getPageSize());

        IPage<UserWatchEntity> pageList = userWatchService.page(page, queryWrapper);
        List<UserWatchEntity> userWatchList = pageList.getRecords();
        List<String> userIdList = new ArrayList<>();
        List<String> adminIdList = new ArrayList<>();
        Boolean finalIsWatch = isWatch;
        userWatchList.forEach(item -> {
            if (finalIsWatch) {
                // 获取他关注了谁
                if (Constants.STR_ONE.equals(item.getIsAdmin())) {
                    adminIdList.add(item.getToUserUid());
                } else {
                    userIdList.add(item.getToUserUid());
                }
            } else {
                // 获取谁关注了他【管理员无法主动关注用户】
                userIdList.add(item.getCreateUserUid());
            }
        });
        List<UserEntity> userList = new ArrayList<>();
        List<AdminDto> adminList = new ArrayList<>();
        if (userIdList.size() > 0) {
            userList = userService.getUserListAndAvatarByIds(userIdList);
        }
        if (adminIdList.size() > 0) {
            R result = adminFeignClient.getAdminListByUids(adminIdList);
            if (result.getCode() == 0) {
                adminList = result.getData(new TypeReference<List<AdminDto>>(){});
            }else {
                throw new FeignException("feign调用异常（通过 ids 获取管理员列表）：失败");
            }
        }
        Map<String, UserEntity> userMap = new HashMap<>();
        Map<String, AdminDto> adminMap = new HashMap<>();
        userList.forEach(item -> {
            userMap.put(item.getUid(), item);
        });
        adminList.forEach(item -> {
            adminMap.put(item.getUid(), item);
        });
        // 关注列表的用户uid
        List<String> watchUserUidList = new ArrayList<>();
        userWatchList.forEach(item -> {
            // 判断是关注者还是被关注者
            if (finalIsWatch) {
                // 获取用户的粉丝
                if (Constants.STR_ONE.equals(item.getIsAdmin())) {
                    item.setAdmin(adminMap.get(item.getToUserUid()));
                } else {
                    item.setUser(userMap.get(item.getToUserUid()));
                }
                // 设置用户id
                watchUserUidList.add(item.getToUserUid());
            } else {
                // 获取用户的粉丝
                item.setUser(userMap.get(item.getCreateUserUid()));
                // 设置用户id
                watchUserUidList.add(item.getCreateUserUid());
            }
        });

        // 获取当前登录用户的信息
        String userUid = RequestHolder.getUserUid();
        // 我关注的用户
        Map<String, String> focusMap = new HashMap<>();
        // 关注我的用户
        Map<String, String> followMap = new HashMap<>();
        if (StringUtils.isNotEmpty(userUid) && watchUserUidList.size() > 0) {
            // 获取我关注的用户
            QueryWrapper<UserWatchEntity> focusQueryWrapper = new QueryWrapper<>();
            focusQueryWrapper.eq(SQLConf.CREATE_USER_UID, userUid);
            focusQueryWrapper.in(SQLConf.TO_USER_UID, watchUserUidList);
            focusQueryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
            List<UserWatchEntity> userWatches = userWatchService.list(focusQueryWrapper);


            // 从我关注的用户中，获取关注我的用户
            if (userWatches.size() > 0) {
                List<String> followUserUidList = new ArrayList<>();
                userWatches.forEach(item -> {
                    followUserUidList.add(item.getToUserUid());
                    focusMap.put(item.getToUserUid(), item.getToUserUid());
                });
                QueryWrapper<UserWatchEntity> followQueryWrapper = new QueryWrapper<>();
                followQueryWrapper.in(SQLConf.CREATE_USER_UID, followUserUidList);
                followQueryWrapper.eq(SQLConf.TO_USER_UID, userUid);
                List<UserWatchEntity> followUserWatches = userWatchService.list(followQueryWrapper);
                followUserWatches.forEach(item -> {
                    followMap.put(item.getCreateUserUid(), item.getCreateUserUid());
                });
            }
        }


        for (UserWatchEntity item : userWatchList) {
            String bizUserUid = "";
            if (finalIsWatch) {
                // 用户的粉丝
                bizUserUid = item.getToUserUid();
            } else {
                // 关注的用户
                bizUserUid = item.getCreateUserUid();
            }
            // 初始化为未关注
            item.setWatchStatus(WatchStatusEnum.NO_WATCH);
            if (StringUtils.isNotEmpty(userUid)) {
                // 关注了用户
                if (focusMap.get(bizUserUid) != null) {
                    // 已关注
                    item.setWatchStatus(WatchStatusEnum.WATCH);
                    if (followMap.get(bizUserUid) != null) {
                        // 互相关注
                        item.setWatchStatus(WatchStatusEnum.MUTUAL_WATCH);
                    }
                }
            }
        }
        return pageList.setRecords(userWatchList);
    }

    @Override
    public Integer checkCurrentUserWatch(UserWatchDto userWatchDto) {
        String userUid = RequestHolder.getUserUid();
        if (StringUtils.isEmpty(userUid)) {
            throw new QueryException(Constants.USER_UID_EMPTY);
        }
//        if (StringUtils.isEmpty(userUid)) {
//            return WatchStatusEnum.NO_WATCH;
//        }
        List<String> userUidList = new ArrayList<>();
        if (StringUtils.isNotEmpty(userWatchDto.getToUserUid())) {
            userUidList.add(userUid);
            userUidList.add(userWatchDto.getToUserUid());
        } else {
            return WatchStatusEnum.NO_WATCH;
        }
        List<UserWatchEntity> list = userWatchService.list(
                new LambdaQueryWrapper<UserWatchEntity>()
                        .in(UserWatchEntity::getCreateUserUid, userUidList)
                        .in(UserWatchEntity::getToUserUid, userUidList)
                        .eq(UserWatchEntity::getStatus, StatusEnum.ENABLE)
        );

        if (list.size() >= 2) {
            // 说明是互相关注
            return WatchStatusEnum.MUTUAL_WATCH;
        } else if (list.size() == 1) {
            // 有一个关注的，判断是自己关注了，还是对方关注了
            UserWatchEntity tempUserWatch = list.get(0);
            // 如果是自己关注
            if (userUid.equals(tempUserWatch.getCreateUserUid())) {
                return WatchStatusEnum.WATCH;
            }
        }
        return WatchStatusEnum.NO_WATCH;
    }

    @Override
    public String addUserWatch(UserWatchDto userWatchDto) {
        HttpServletRequest request = RequestHolder.getRequest();
        Object userUid = request.getAttribute(SysConf.USER_UID);
        if (userUid == null) {
            return ResultUtil.errorWithMessage("用户未登录");
        }
        if (userUid.equals(userWatchDto.getToUserUid())) {
            return ResultUtil.errorWithMessage("您无法关注自己");
        }
        if (userWatchDto.getIsAdmin() == Constants.NUM_ONE) {
            throw new InsertException("无法关注管理员");
        }

        // 判断该用户是否被关注过
        QueryWrapper<UserWatchEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.CREATE_USER_UID, userUid.toString());
        queryWrapper.eq(SQLConf.TO_USER_UID, userWatchDto.getToUserUid());
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        int count = userWatchService.count(queryWrapper);
        if (count > 0) {
            return ResultUtil.errorWithMessage("您已关注过该用户");
        }

        UserWatchEntity userWatch = new UserWatchEntity();
        userWatch.setCreateUserUid(userUid.toString());
        userWatch.setToUserUid(userWatchDto.getToUserUid());
        userWatch.setIsAdmin(userWatchDto.getIsAdmin());
        boolean isSave = userWatch.insert();

        if (isSave) {
            domainEventUtil.publishEvent(EventAction.WATCH_ADD, userWatch);
        }
        return ResultUtil.successWithMessage("关注成功");
    }

    @Override
    public String deleteUserWatch(UserWatchDto userWatchDto) {
        HttpServletRequest request = RequestHolder.getRequest();
        Object userUid = request.getAttribute(SysConf.USER_UID);
        if (userUid == null) {
            return ResultUtil.errorWithMessage("用户未登录");
        }
        QueryWrapper<UserWatchEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.CREATE_USER_UID, userUid.toString());
        queryWrapper.eq(SQLConf.TO_USER_UID, userWatchDto.getToUserUid());
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.last(SysConf.LIMIT_ONE);
        UserWatchEntity userWatch = userWatchService.getOne(queryWrapper);
        if (userWatch == null) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        } else {
            userWatch.setStatus(StatusEnum.DISABLED);
            boolean isSave = userWatch.updateById();
            if (isSave) {
                domainEventUtil.publishEvent(EventAction.WATCH_CANCEL, userWatch);
            }
            return ResultUtil.successWithMessage("取消关注成功");
        }
    }

    // endregion
    /***************************** web:end **************************/


    @Override
    public List<UserWatchEntity> convertUserWatchList(Collection<UserWatchEntity> userWatchList) {
        List<String> userIdList = new ArrayList<>();
        List<UserWatchEntity> resultList = new ArrayList<>();
        userWatchList.forEach(item -> {
            userIdList.add(item.getCreateUserUid());
        });
        List<UserEntity> userList = new ArrayList<>();
        if (userIdList.size() > 0) {
            userList = userService.getUserListAndAvatarByIds(userIdList);
        }

//        userList = userService.convertUserList(userList);

        Map<String, UserEntity> userMap = new HashMap<>();
        userList.forEach(item -> {
            userMap.put(item.getUid(), item);
        });
        userWatchList.forEach(item -> {
            item.setUser(userMap.get(item.getCreateUserUid()));
            resultList.add(item);
        });
        return resultList;
    }

    /**
     * 获取用户关注的用户id列表
     *
     * @param userUid
     * @return
     */
    @Override
    public List<String> listUserWatchIdsByUserUid(String userUid) {
        List<UserWatchEntity> userWatchList = userWatchService.list(new LambdaQueryWrapper<UserWatchEntity>()
                .eq(UserWatchEntity::getCreateUserUid, userUid)
                .eq(UserWatchEntity::getStatus, StatusEnum.ENABLE));
        return userWatchList.stream().map(UserWatchEntity::getToUserUid).collect(Collectors.toList());

    }
}